package com.baoai.dao;

import com.baoai.MyIkAnalyzer;
import com.baoai.dto.BaseDto;
import com.baoai.util.BaseUtil;
import com.baoai.util.DocumentUtils;
import com.baoai.util.LuenceUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * Created by xiaren on 2017/4/6.
 */
@Repository
public class IndexDao {

    private static final Logger LOGGER = LoggerFactory.getLogger(IndexDao.class);

    /**
     * 往索引里面添加数据
     *
     * @param sourceObj
     * @throws IOException
     */
    public synchronized Object save(BaseDto sourceObj) throws IOException {
        Document doc = DocumentUtils.getDocumentByObj(sourceObj);
        IndexWriterConfig config = new IndexWriterConfig(LuenceUtils.getAnalyzer());
        IndexWriter indexWriter = new IndexWriter(LuenceUtils.getDirectory(), config);
        indexWriter.addDocument(doc);
        LuenceUtils.closeIndexWriter(indexWriter);
        return sourceObj;
    }

    /**
     * 修改
     *
     * @return
     * @throws IOException
     */
    public Object update(BaseDto targetDto) throws IOException {
        Document doc = DocumentUtils.getDocumentByObj(targetDto);
        IndexWriterConfig config = new IndexWriterConfig(LuenceUtils.getAnalyzer());
        IndexWriter indexWriter = new IndexWriter(LuenceUtils.getDirectory(), config);
        Term term = new Term("id", targetDto.getId());
        indexWriter.updateDocument(term, doc);
        LuenceUtils.closeIndexWriter(indexWriter);
        return targetDto;
    }

    /**
     * 根据条件查询单个
     *
     * @return
     * @throws IOException
     */
    public Object findIndexById(Query query) throws IOException {
        DirectoryReader ireader = null;
        File file = new File(LuenceUtils.filePath);
        if (!file.exists()) {
            return null;
        }
        try {
            ireader = DirectoryReader.open(LuenceUtils.getDirectory());
        } catch (IndexNotFoundException e) {
            e.printStackTrace();
            return null;
        }
        IndexSearcher searcher = new IndexSearcher(ireader);

        TopDocs rs = searcher.search(query, 1);
        if (rs.scoreDocs.length > 0) {
            Document firstHit = searcher.doc(rs.scoreDocs[0].doc);
            Object obj = DocumentUtils.getObjByDocument(firstHit);
            return obj;
        }
        if (ireader != null && ireader.isCurrent()) {
            ireader.close();
        }

        return null;
    }


    /**
     * 根据条件公共查询
     *
     * @param query
     * @param sort
     * @param pageIndex
     * @param pageSize
     * @return
     * @throws IOException
     */
    public List<Object> commQuery(Query query, Sort sort, int pageIndex, int pageSize) throws IOException {
        List<Object> objectList = new ArrayList<>();
        DirectoryReader ireader = null;
        File file = new File(LuenceUtils.filePath);
        if (!file.exists()) {
            return null;
        }
        ireader = DirectoryReader.open(LuenceUtils.getDirectory());
        IndexSearcher searcher = new IndexSearcher(ireader);

        TopDocs rs = null;
        if (sort == null) {
            rs = searcher.search(query, 100000);
        } else {
            rs = searcher.search(query, 100000, sort);      // 一次总共查询10万条数据，内存应该不会暴
        }
        int start = (pageIndex - 1) * pageSize;
        int end = pageIndex * pageSize;
        end = end > rs.scoreDocs.length ? rs.scoreDocs.length : end;
        for (int i = start; i < end; i++) {
            Document firstHit = searcher.doc(rs.scoreDocs[i].doc);
            Object obj = DocumentUtils.getObjByDocument(firstHit);
            objectList.add(obj);
        }
        return objectList;
    }

    /**
     * 查询单个数据
     *
     * @param query
     * @param sort
     * @return
     * @throws IOException
     */
    public Object getSignIndex(Query query, Sort sort) throws IOException {
        List<Object> objectList = new ArrayList<>();
        DirectoryReader ireader = null;
        File file = new File(LuenceUtils.filePath);
        if (!file.exists()) {
            return null;
        }
        ireader = DirectoryReader.open(LuenceUtils.getDirectory());
        IndexSearcher searcher = new IndexSearcher(ireader);

        TopDocs rs = null;
        if (sort == null) {
            rs = searcher.search(query, 1);
        } else {
            rs = searcher.search(query, 1, sort);
        }
        Object obj = null;
        if (rs.scoreDocs.length > 0) {
            Document firstHit = searcher.doc(rs.scoreDocs[0].doc);
            obj = DocumentUtils.getObjByDocument(firstHit);
        }
        return obj;
    }


    /**
     * 查询所有索引数据
     *
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public List<Object> queryAllList() throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
        List<Object> objectList = new ArrayList<>();
        DirectoryReader ireader = null;
        File file = new File(LuenceUtils.filePath);
        if (!file.exists()) {
            return null;
        }
        ireader = DirectoryReader.open(LuenceUtils.getDirectory());
        IndexSearcher searcher = new IndexSearcher(ireader);
        Query query = new MatchAllDocsQuery();
        TopDocs rs = searcher.search(query, 10000);
        for (int i = 0; i < rs.scoreDocs.length; i++) {
            Document firstHit = searcher.doc(rs.scoreDocs[i].doc);
            Object obj = DocumentUtils.getObjByDocument(firstHit);
            objectList.add(obj);
        }
        if (ireader != null && ireader.isCurrent()) {
            ireader.close();
        }
        return objectList;
    }

    /**
     * 删除索引数据
     *
     * @throws IOException
     */
    public void deleteAllIndex() throws IOException {
        File file = new File(LuenceUtils.filePath);
        if (!file.exists()) {
            return;
        }
        IndexWriter writer = null;
        IndexWriterConfig writerConfig = new IndexWriterConfig(new MyIkAnalyzer());
        writer = new IndexWriter(LuenceUtils.getDirectory(), writerConfig);
        writer.deleteDocuments(new MatchAllDocsQuery());
        if (writer != null && writer.isOpen()) {
            writer.close();
        }
    }

    /**
     * 根据id查询
     *
     * @param id
     * @param cls
     * @throws IOException
     */
    public void deleteById(String id, Class cls) throws IOException {

        IndexWriterConfig config = new IndexWriterConfig(LuenceUtils.getAnalyzer());
        IndexWriter indexWriter = new IndexWriter(LuenceUtils.getDirectory(), config);
        Term term = new Term("id", id);
        indexWriter.deleteDocuments(term);
        LuenceUtils.closeIndexWriter(indexWriter);
    }


}